package cn.edu.njuit.webserver.securityserver.common;

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

import static cn.edu.njuit.webserver.securityserver.common.ResultCode.*;

/**
 * @Author guzy
 * @Description 异常处理
 * @Date 2022/4/21 17:54
 **/

@RestControllerAdvice
@Slf4j
public class ErrorExceptionAdvice {

    @ExceptionHandler
    public Result doException(Exception e) {
        log.error(e.getMessage(), e);
        return Result.failure(SYSTEM_INNER_ERROR,e.getMessage());
    }

    /**
     * @param e
     * @return Result
     * @Description: 基本类型参数入参校验异常返回数据处理
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result basicTypeParamsCheckException(ConstraintViolationException e) {
        log.info("============基本类型参数入参校验异常============");
        List<String> defaultMsg = e.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.toList());
        return Result.failure(PARAM_TYPE_BIND_ERROR, defaultMsg.get(0));
    }

    /**
     * 参数校验不通过异常处理
     *
     * @param e
     * @return
     * @see
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        log.info("============参数校验不通过异常处理============");
        List<String> defaultMsg = e.getBindingResult().getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.toList());
        return Result.failure(PARAM_IS_INVALID,defaultMsg.get(0));
    }


    /**
     * @param e
     * @return Result
     * @Description: 实体类型参数入参校验异常返回数据处理
     */
    @ExceptionHandler(BindException.class)
    public Result entityTypeParamsCheckException(BindException e) {
        log.info("============实体类型参数入参校验异常============");
        return Result.failure(PARAM_TYPE_BIND_ERROR,e.getBindingResult().getFieldError().getDefaultMessage());
    }

    /**
     * required参数缺失异常
     *
     * @param exception
     * @return
     * @see
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public Result missingServletRequestParameterException(MissingServletRequestParameterException exception) {
        String parameterName = exception.getParameterName();
        String parameterType = exception.getParameterType();
        StringBuffer errStr = new StringBuffer();
        errStr.append("[").append(parameterName)
                .append("]")
                .append(":")
                .append("is required,")
                .append("type")
                .append(":")
                .append(parameterType);

        log.error(exception.getMessage(), exception);
        return Result.failure(PARAM_NOT_COMPLETE,errStr.toString());
    }

    /**
     *  token失效
     * @param e
     * @return
     */
    @ExceptionHandler(JWTVerificationException.class)
    public Result jwtVerificationException(JWTVerificationException e){
        log.info("============token校验失败============");
        return Result.failure(TOKEN_EXPIRED,e.getMessage());

    }

}
